home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / irhash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-06  |  20.3 KB  |  592 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.
  4.  
  5.    Brewster@think.com
  6. */
  7.  
  8. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  9.  
  10.  
  11. /* The memory hashtables for building an index. */
  12. /* -brewster 5/90 */
  13.  
  14. /* Change log:
  15.  * $Log: irhash.c,v $
  16.  * Revision 1.8  1994/09/07  13:29:22  pfeifer
  17.  * ctype is now included from cdialect.h after inclusion of string.h.
  18.  * Since ctype.h (the local version defines strcmp and friends, inclusion o
  19.  * of string.h after that caused probems
  20.  *
  21.  * Revision 1.7  1994/06/20  15:41:35  huynh1
  22.  * missing parameter field_id added by calling
  23.  * field_flush_memory_hashtable_to_disk(db, false, field_id).
  24.  *
  25.  * Revision 1.6  1994/06/06  11:01:27  huynh1
  26.  * add_word, look_up_word updated.
  27.  *
  28.  * Revision 1.5  1994/05/27  09:23:26  huynh1
  29.  * add_word, field_add_word updated. beta
  30.  *
  31.  * Revision 1.4  1994/05/20  12:56:13  pfeifer
  32.  * beta
  33.  *
  34.  * Revision 1.3  1994/03/08  20:42:41  huynh1
  35.  * Patchlevel 04
  36.  *
  37.  * Revision 1.2  1994/02/14  10:46:51  huynh1
  38.  * new code for field concept added.
  39.  *
  40.  * Revision 1.1  1993/02/16  15:05:35  freewais
  41.  * Initial revision
  42.  *
  43.  * Revision 1.16  92/03/20  11:04:33  jonathan
  44.  * Added code to handle switches for word_pairs and word_postition info.
  45.  * 
  46.  * Revision 1.15  92/02/12  13:26:28  jonathan
  47.  * Added "$Log" so RCS will put the log message in the header
  48.  * 
  49. */
  50.  
  51. /* main functions:
  52.  *   add_word
  53.  *   finished_add_word
  54.  *   look_up_word
  55.  *
  56.  * The idea is to store up a bunch of words before going to disk.
  57.  * A word entry points to where it will go on disk, and
  58.  * accumulates the entries before doing it.
  59.  *
  60.  * Some of the policy issues in this file are:
  61.  *   How much weight should the first occurance of a word in a document get
  62.  *   over the other occurances.  The first occurance should be worth more
  63.  *   so that words with 3 occurances of "dog" and not "cat"'s should not 
  64.  *   win out over 1 "dog" and 1 "cat" if the question is "Tell me about cats
  65.  *   torture dogs"
  66.  *   The extra weight is 5 at this point.
  67.  *
  68.  */
  69.  
  70. /* To Do:
  71.  *  done: Improve the hashing functions.
  72.  *  done: stop inserting into hash table after max number have been accumulated
  73.  *  done: make flush not flush buffers that are too big.
  74.  */
  75.  
  76. #include "panic.h"
  77. #include "cutil.h"
  78. #include "irfiles.h"
  79. #include "irhash.h"
  80. #include "stoplist.h"
  81. #include "irinv.h"
  82. #ifdef NEW_WEIGHT /* tung, 5/94 */
  83. #include "weight.h"
  84. #endif
  85.  
  86. #ifdef UNIX
  87. #define PRINT_AS_INDEXING true /* also defined in irtfiles.c and irfiles.c */
  88. #else 
  89. #define PRINT_AS_INDEXING false
  90. #endif
  91.  
  92. /* ================================
  93.    ===  Word Occurance Buffers  ===
  94.    ================================ */
  95.  
  96. /* Word occurance buffers
  97.  * This is a simple memory allocator for use with the word memory hashtable.
  98.  * Since the buffers are tiny, this is done as a copy-sweep GC scheme.
  99.  * Oh, I long for the storage system of lisp.
  100.  */
  101. unsigned char *first_word_occurance_buffer = NULL;  /* allocate blocks out of this */
  102. unsigned char *last_word_occurance_buffer = NULL;
  103. long word_occurance_block_length = 256000;  /* maybe this should be larger? */
  104. unsigned char * word_occurance_free_ptr = NULL;
  105.  
  106. unsigned char *make_word_occurrance_block(size)
  107. long size;
  108.  
  109. {
  110.   /* allocates a word_occurance_block out of the buffers */
  111.   /* old way: s_malloc((size_t)size); */
  112.   /* returns a pointer to a piece of memory */
  113.   if(NULL == first_word_occurance_buffer){
  114.     /* initialize it */
  115.     first_word_occurance_buffer = 
  116.       (unsigned char *)s_malloc(MAXIMUM(word_occurance_block_length,
  117.                sizeof(size_t)+ size));
  118.     *(unsigned char **)first_word_occurance_buffer = NULL; /* set the end */
  119.     last_word_occurance_buffer = first_word_occurance_buffer;
  120.     word_occurance_free_ptr = first_word_occurance_buffer + sizeof(size_t);
  121.   }
  122.   if((long)word_occurance_free_ptr + size >= 
  123.      word_occurance_block_length + (long)last_word_occurance_buffer){
  124.     /* then allocate a new block */
  125.     unsigned char * new_block = (unsigned char *)s_malloc(MAXIMUM(word_occurance_block_length,
  126.                         sizeof(size_t)+ size));
  127.     *(unsigned char **)new_block = NULL; /* set the end of the chain */
  128.     *(unsigned char **)last_word_occurance_buffer = new_block;
  129.     word_occurance_free_ptr = new_block + sizeof(size_t);
  130.     last_word_occurance_buffer = new_block;
  131.   }
  132.   /* allocate away */    
  133.   { unsigned char * answer = word_occurance_free_ptr;
  134.     word_occurance_free_ptr += size;    
  135.     return(answer);  
  136.   }
  137. }
  138.  
  139. void free_word_occurance_block(block)
  140. unsigned char *block;
  141. {
  142.   /* this is not used with the new scheme, but is here in case
  143.      malloc is a win on some systems */
  144.   /* old way s_free(block); */
  145. }
  146.  
  147. static void flush_word_occur_bufs_internal
  148.   _AP((unsigned char* head_of_list));
  149.  
  150. static void flush_word_occur_bufs_internal(head_of_list)
  151. unsigned char* head_of_list;
  152. /* frees all word occurance buffers.  This should be done with care */
  153. {      
  154.   while(1){
  155.     unsigned char * next_block;
  156.     if(NULL == head_of_list)
  157.       break;
  158.     next_block = *(unsigned char **)head_of_list;
  159.     s_free(head_of_list);
  160.     head_of_list = next_block;
  161.   }
  162. }
  163.  
  164. void flush_word_occurance_buffers()
  165. {
  166.   /* frees all word occurance buffers.  This should be done with care */
  167.   flush_word_occur_bufs_internal(first_word_occurance_buffer);
  168.   first_word_occurance_buffer = NULL;
  169.   word_occurance_free_ptr = NULL;
  170.   last_word_occurance_buffer = NULL;
  171. }
  172.  
  173. /* ---------------------------------------------------- */
  174. #ifdef NEW_WEIGHT /* tung, 5/94 */
  175. extern long max_term_frequency; /* defined in weight.c */
  176. #endif
  177.  
  178. static hash_entry* look_up_word _AP((char* word,hashtable*
  179.                      the_word_memory_hashtable));
  180.   
  181. static hash_entry* 
  182. look_up_word(word,the_word_memory_hashtable)
  183. char* word;
  184. hashtable* the_word_memory_hashtable;
  185. {
  186.   hash_entry * answer = get_hash(word, the_word_memory_hashtable);
  187.   
  188.   if(NULL != answer)
  189.     return(answer);
  190.   else{
  191.     hash_entry wrd_entry;
  192.     answer = put_hash(word, the_word_memory_hashtable, &wrd_entry);
  193.     answer->number_of_occurances = 0;
  194.     answer->memory_ptr = 
  195.       make_word_occurrance_block(WORD_MEMORY_INIT_BLOCK_SIZE);
  196.     answer->current_memory_ptr = answer->memory_ptr;
  197.     answer->memory_size = WORD_MEMORY_INIT_BLOCK_SIZE;
  198.     answer->current_doc_id = 0;
  199. #ifdef NEW_WEIGHT /* tung, 5/94 */
  200.     answer->occurances_in_doc = 0;
  201. #endif
  202.     return(answer);
  203.   }
  204. }
  205.  
  206. static unsigned char add_weight _AP((long current_weight,long new_weight));
  207.  
  208. static unsigned char 
  209. add_weight(current_weight,new_weight)
  210. long current_weight;
  211. long new_weight;
  212. /* add a new weight to the existing one */
  213. {
  214. #ifndef NEW_WEIGHT /* tung, 5/94 */
  215.   /* this should be smarter than this, like doing the log or something */
  216.   if(127 < (current_weight + new_weight)){
  217.     /* the max char.  should be 255, but does not work on all compilers */
  218.     return(127);
  219.   }
  220.   else{
  221.     return(current_weight + new_weight);
  222.   }
  223. #else
  224.   return(current_weight + new_weight);
  225. #endif
  226. }
  227.  
  228. static unsigned char* more_memory _AP((unsigned char* current_memory_ptr,
  229.                        long current_memory_size,
  230.                        long new_size));
  231.  
  232. static unsigned char* more_memory(current_memory_ptr,current_memory_size,new_size)
  233. unsigned char* current_memory_ptr;
  234. long current_memory_size;
  235. long new_size;
  236. /* Allocates more memory for a hash_entry.  It transfers all the bytes 
  237.  * from the old to the new and then returns the new.
  238.  */
  239. {
  240.   unsigned char* new_memory = NULL;
  241.   if(current_memory_size > new_size){
  242.     panic("trying to contract a hash_entry block.  This is not right\n");
  243.   }
  244.   new_memory = make_word_occurrance_block(new_size);
  245.   if(NULL == new_memory){
  246.     panic("Out of memory.");
  247.   }
  248.   memset(new_memory, 0, new_size);
  249.   memmove(new_memory, current_memory_ptr, (size_t)current_memory_size); 
  250.   return(new_memory);
  251. }
  252.  
  253. static long more_memory_size _AP((long current_size,
  254.                   long number_of_occurances));
  255.  
  256. static long more_memory_size(current_size,number_of_occurances)
  257. long current_size;
  258. long number_of_occurances;
  259. /* This is pretty important to get right.  This is a place holder */
  260. {
  261.   return(MAXIMUM(2 * current_size, WORD_MEMORY_INIT_BLOCK_SIZE));
  262. }
  263.  
  264. long write_bytes_to_memory(value,size,ptr)
  265. long value;
  266. long size;
  267. unsigned char* ptr;
  268. {
  269.   /* writes the number into memory lsb first.  
  270.      returns the number of bytes written */
  271.   long i;
  272.   long original_value = value;
  273.  
  274.   if(size < 0) /* paranoia */
  275.     panic("attempting to write a negative number of bytes");
  276.  
  277.   ptr += size; /* start at the end of the block and write backwards */
  278.   for (i = 0; i < size; i++){
  279.     ptr--;
  280.     *ptr = (unsigned char)(value & 0xFF);
  281.     value = value >> 8;
  282.   }
  283.   if(value != 0)
  284.     panic("In a call to write_bytes_to_memory, the value %ld can not be represented in %ld bytes", original_value, size);
  285.  
  286.   return(size);
  287. }
  288.         
  289. /* adds a word to the hashtable. Returns the 0 if successful. 
  290.    See irext.h for more documentation.
  291.  */
  292. long add_word(word, char_pos, line_pos,
  293.           weight, doc_id, date, word_pair, db, word_position)
  294.      char *word;    /* the word to be indexed, this could be a
  295.                word pair. If NULL there are no more words
  296.                to be indexed */
  297.      long char_pos;    /* the position of the start of the
  298.                word */
  299.      long line_pos;    /* this is passed for the best
  300.                section calculation */
  301.      long weight;    /* how important the word looks
  302.                syntactically (such as is it bold)
  303.                NOT used by signature system */
  304.      long doc_id;     /* current document, this will never be 0 */
  305.      time_t date; /* display day of this document, 0 if not known */
  306.      long word_pair;
  307.      database* db; /* database to insert the document */
  308.      boolean word_position; /* whether to have multiple entries for words in a document */
  309. {
  310.   /* look up the word in the hashtable */
  311.   /* creates it if necessary */    
  312.   hash_entry* wrd_entry; 
  313.   char* newword;
  314.   t_Synonym* syn_Table = db->syn_Table;
  315.   int syn_Table_Size = db->syn_Table_Size;
  316.   hashtable * the_word_memory_hashtable = db->the_word_memory_hashtable;
  317.  
  318.   /* printf("Word: '%s' doc_id: %ld, pos: %ld, weight: %ld\n",
  319.      word, doc_id, char_pos, weight); */
  320.  
  321.   if(NULL == db->the_word_memory_hashtable){
  322.     panic("The memory word hashtable is not defined.");
  323.   }
  324.  
  325.   /* if we have indexed enough words flush the memory copies to disk. */
  326.   if(db->number_of_words_in_hashtable == db->flush_after_n_words) {
  327. #ifdef NEW_WEIGHT /* tung, 5/94 */
  328.     extern long number_of_bucket_ids; /* defined in irtfiles.c */
  329.     long prev_number_of_bucket_ids = number_of_bucket_ids;
  330.     save_terms_for_doc(&number_of_bucket_ids, db);
  331. #endif
  332.     flush_memory_hashtable_to_disk(db, false);
  333. #ifdef NEW_WEIGHT /* tung, 5/94 */
  334.     number_of_bucket_ids = prev_number_of_bucket_ids;
  335.     add_terms_saved(false, &number_of_bucket_ids, doc_id, db);
  336. #endif
  337.   }
  338.   
  339.   /* perform synonym table lookup and if the word is changed skip WordRoot */
  340.   newword = lookup_Synonym( word,syn_Table,syn_Table_Size );
  341.   strncpy( word,newword,MAX_WORD_LENGTH );
  342.   wrd_entry = look_up_word(word, the_word_memory_hashtable);
  343.   wrd_entry->number_of_occurances ++;
  344.  
  345.   if(wrd_entry->number_of_occurances > MAX_OCCURANCES){
  346.     /* do nothing. we have enough of that word */
  347.   }
  348.   else{
  349.     /* we have a word to add */
  350.     db->number_of_words_in_hashtable ++;
  351.     
  352.     if(word_position || doc_id != wrd_entry->current_doc_id){
  353.       /* then we have a new doc_id to add to the memory block */
  354.       
  355.       /* check to see if we need more memory */
  356.       if((wrd_entry->memory_size -
  357.           (wrd_entry->current_memory_ptr - 
  358.            wrd_entry->memory_ptr) 
  359.           < 
  360.           INDEX_ELEMENT_SIZE)){
  361.         /* we need more memory. this makes more and frees the old*/
  362.         unsigned char* old_memory_ptr = wrd_entry->memory_ptr;
  363.         
  364.         long new_size = 
  365.           more_memory_size(wrd_entry->memory_size,
  366.                            wrd_entry->number_of_occurances);
  367.         /* cprintf(PRINT_AS_INDEXING, "Get more memory %ld bytes for %s\n", new_size, word); */
  368.         wrd_entry->memory_ptr = 
  369.           more_memory(wrd_entry->memory_ptr, wrd_entry->memory_size,
  370.                       new_size);
  371.         wrd_entry->current_memory_ptr = 
  372.           wrd_entry->memory_ptr + /* new offset */
  373.             (wrd_entry->current_memory_ptr - old_memory_ptr);
  374.         /* just being paranoid... no longer illegal
  375.            if(wrd_entry->current_memory_ptr == wrd_entry->memory_ptr)
  376.            panic("After allocating more memory, the size went to 0");
  377.            */
  378.         wrd_entry->memory_size = new_size;
  379.       }                /* finished making more memory */
  380.       
  381.       /* add away */
  382.       wrd_entry->current_memory_ptr +=
  383.         write_bytes_to_memory(doc_id, DOCUMENT_ID_SIZE,
  384.                               wrd_entry->current_memory_ptr);
  385.       wrd_entry->current_memory_ptr +=
  386.         write_bytes_to_memory(char_pos, 
  387.                               CHARACTER_POSITION_SIZE,
  388.                               wrd_entry->current_memory_ptr);
  389. #ifdef NEW_WEIGHT /* tung, 5/94 */
  390.       wrd_entry->current_memory_ptr +=
  391.     write_bytes_to_memory(0,
  392.                   NEW_WEIGHT_SIZE,
  393.                               wrd_entry->current_memory_ptr);
  394.       wrd_entry->occurances_in_doc += weight;
  395.       if(wrd_entry->occurances_in_doc > max_term_frequency)
  396.     max_term_frequency = wrd_entry->occurances_in_doc;
  397. #else
  398.       wrd_entry->current_memory_ptr +=
  399.         write_bytes_to_memory(weight +
  400.                               /* add 5 since for the first one */
  401.                               (doc_id != wrd_entry->current_doc_id)?5:0,
  402.                               WEIGHT_SIZE,
  403.                               wrd_entry->current_memory_ptr);
  404. #endif
  405.       wrd_entry->current_doc_id = doc_id;
  406.       
  407.     }
  408.     else{
  409.       /* The word is already there,
  410.        * just increment the weight in the record.
  411.        * This will change when/if position information is kept (for proximity).
  412.        */
  413.       if(wrd_entry->current_memory_ptr == wrd_entry->memory_ptr){
  414.         panic("Memory hashtable error. Recorded doc_id %ld, current doc_id %ld\n",
  415.               wrd_entry->current_doc_id, doc_id);
  416.       }
  417. #ifdef NEW_WEIGHT /* tung, 5/94 */
  418.       wrd_entry->occurances_in_doc += weight;
  419.       if(wrd_entry->occurances_in_doc > max_term_frequency)
  420.     max_term_frequency = wrd_entry->occurances_in_doc;
  421. #else
  422.       *(wrd_entry->current_memory_ptr - 1) =
  423.         add_weight(*(wrd_entry->current_memory_ptr - 1), weight);
  424. #endif
  425.     }
  426.   }
  427.  
  428.   return(0L);
  429. }
  430.  
  431. #ifdef FIELDS /* tung, 1/94 */
  432. long field_add_word(word, char_pos, line_pos,
  433.             weight, doc_id, date, word_pair, db, word_position)
  434.      char *word;    /* the word to be indexed, this could be a
  435.                word pair. If NULL there are no more words
  436.                to be indexed */
  437.      long char_pos;    /* the position of the start of the
  438.                word */
  439.      long line_pos;    /* this is passed for the best
  440.                section calculation */
  441.      long weight;    /* how important the word looks
  442.                syntactically (such as is it bold)
  443.                NOT used by signature system */
  444.      long doc_id;     /* current document, this will never be 0 */
  445.      time_t date; /* display day of this document, 0 if not known */
  446.      long word_pair;
  447.      database* db; /* database to insert the document */
  448.      boolean word_position; /* whether to have multiple entries for words in a document */
  449. {
  450.   /* look up the word in the hashtable */
  451.   /* creates it if necessary */    
  452.  
  453.   char* newword;
  454.   t_Synonym* syn_Table = db->syn_Table;
  455.   int syn_Table_Size = db->syn_Table_Size;
  456.   hashtable * the_word_field_memory_hashtable = db->the_word_memory_hashtable;
  457.   hash_entry* wrd_field_entry;
  458.   long field_id = db->current_field_position; 
  459.   
  460.   /* printf("Word: '%s' doc_id: %ld, pos: %ld, weight: %ld\n",
  461.      word, doc_id, char_pos, weight); */
  462.   
  463.   if(NULL == db->the_word_memory_hashtable){
  464.     panic("The memory word hashtable is not defined.");
  465.   }
  466.   
  467.   /* if we have indexed enough words flush the memory copies to disk. */
  468.   if(db->fields[field_id].number_of_words_in_hashtable == db->flush_after_n_words) {
  469. #ifdef NEW_WEIGHT /* tung, 5/94 */
  470.     extern long number_of_bucket_ids; /* defined in irtfiles.c */
  471.     long prev_number_of_bucket_ids = number_of_bucket_ids;
  472.     save_terms_for_doc(&number_of_bucket_ids, db);
  473. #endif
  474.     field_flush_memory_hashtable_to_disk(db, false, field_id);
  475. #ifdef NEW_WEIGHT /* tung, 5/94 */
  476.     number_of_bucket_ids = prev_number_of_bucket_ids;
  477.     add_terms_saved(true, &number_of_bucket_ids, doc_id, db);
  478. #endif
  479.   }
  480.   
  481.     /* perform synonym table lookup and if the word is changed skip WordRoot */
  482.     newword = lookup_Synonym( word,syn_Table,syn_Table_Size );
  483.     strncpy( word,newword,MAX_WORD_LENGTH );
  484.  
  485.   wrd_field_entry = 
  486.     look_up_word(word, the_word_field_memory_hashtable);
  487.   wrd_field_entry->number_of_occurances++;
  488.  
  489.   if(wrd_field_entry->number_of_occurances > MAX_OCCURANCES){
  490.     /* do nothing. we have enough of that word */
  491.   }
  492.   else{
  493.     /* we have a word to add */
  494.     db->fields[field_id].number_of_words_in_hashtable++;
  495.     
  496.     if(word_position || doc_id != wrd_field_entry->current_doc_id){
  497.       /* then we have a new doc_id to add to the memory block */
  498.       
  499.       /* check to see if we need more memory */
  500.       if((wrd_field_entry->memory_size -
  501.           (wrd_field_entry->current_memory_ptr - 
  502.            wrd_field_entry->memory_ptr) 
  503.           < 
  504.           INDEX_ELEMENT_SIZE)){
  505.         /* we need more memory. this makes more and frees the old*/
  506.         unsigned char* old_memory_ptr = wrd_field_entry->memory_ptr;
  507.         
  508.         long new_size = 
  509.           more_memory_size(wrd_field_entry->memory_size,
  510.                            wrd_field_entry->number_of_occurances);
  511.         /* cprintf(PRINT_AS_INDEXING, "Get more memory %ld bytes for %s\n", new_size, word); */
  512.         wrd_field_entry->memory_ptr = 
  513.           more_memory(wrd_field_entry->memory_ptr, 
  514.               wrd_field_entry->memory_size, new_size);
  515.         wrd_field_entry->current_memory_ptr = 
  516.           wrd_field_entry->memory_ptr + /* new offset */
  517.             (wrd_field_entry->current_memory_ptr - old_memory_ptr);
  518.         /* just being paranoid... no longer illegal
  519.            if(wrd_field_entry->current_memory_ptr == wrd_field_entry->memory_ptr)
  520.            panic("After allocating more memory, the size went to 0");
  521.            */
  522.         wrd_field_entry->memory_size = new_size;
  523.       }                /* finished making more memory */
  524.       
  525.       /* add away */
  526.       wrd_field_entry->current_memory_ptr +=
  527.         write_bytes_to_memory(doc_id, DOCUMENT_ID_SIZE,
  528.                               wrd_field_entry->current_memory_ptr);
  529.       wrd_field_entry->current_memory_ptr +=
  530.         write_bytes_to_memory(char_pos, 
  531.                               CHARACTER_POSITION_SIZE,
  532.                               wrd_field_entry->current_memory_ptr);
  533. #ifdef NEW_WEIGHT /* tung, 5/94 */
  534.       wrd_field_entry->current_memory_ptr +=
  535.         write_bytes_to_memory(0,
  536.                               NEW_WEIGHT_SIZE,
  537.                               wrd_field_entry->current_memory_ptr);
  538.       wrd_field_entry->occurances_in_doc += weight;
  539.       if(wrd_field_entry->occurances_in_doc > max_term_frequency)
  540.     max_term_frequency = wrd_field_entry->occurances_in_doc;
  541. #else
  542.       wrd_field_entry->current_memory_ptr +=
  543.         write_bytes_to_memory(weight +
  544.                               /* add 5 since for the first one */
  545.                               (doc_id != wrd_field_entry->current_doc_id)?5:0,
  546.                               WEIGHT_SIZE,
  547.                               wrd_field_entry->current_memory_ptr);
  548. #endif
  549.       wrd_field_entry->current_doc_id = doc_id;
  550.       
  551.     }
  552.     else{
  553.       /* The word is already there,
  554.        * just increment the weight in the record.
  555.        * This will change when/if position information is kept (for proximity).
  556.        */
  557.       if(wrd_field_entry->current_memory_ptr == wrd_field_entry->memory_ptr){
  558.         panic("Memory hashtable error. Recorded doc_id %ld, current doc_id %ld\n",
  559.               wrd_field_entry->current_doc_id, doc_id);
  560.       }
  561. #ifdef NEW_WEIGHT /* tung, 5/94 */
  562.       wrd_field_entry->occurances_in_doc += weight;
  563.       if(wrd_field_entry->occurances_in_doc > max_term_frequency)
  564.     max_term_frequency = wrd_field_entry->occurances_in_doc;
  565. #else
  566.       *(wrd_field_entry->current_memory_ptr - 1) =
  567.         add_weight(*(wrd_field_entry->current_memory_ptr - 1), weight);
  568. #endif
  569.     }
  570.   }
  571.   return(0L);
  572. }
  573. #endif
  574.  
  575. void add_stop_words(the_word_memory_hashtable)
  576. hashtable *the_word_memory_hashtable;
  577.      /* add the stop words to the hashtable.  this must be done before
  578.     adding other words */
  579. {
  580.   init_stop_list();
  581.   while(true){
  582.     char *word = next_stop_word();
  583.     hash_entry* wrd_entry;
  584.  
  585.     if(NULL == word)
  586.       break;
  587.     wrd_entry = look_up_word(word, the_word_memory_hashtable);
  588.     wrd_entry->number_of_occurances = STOP_WORD_FLAG;
  589.   }
  590. }
  591.  
  592.